Nixでfix関数を使ってAttribute Setsをoverrideする
code:nix repl
fix = f: let result = f result; in result
Haskellなどと同じmrsekut.icon
code:nix repl
pkgs = self: { a = 100; b = self.a + 200; }
self: { a = 1; b = self.a+100; }の部分で、自身を参照している
これをfixに適用することで、値が得られる
code:nix repl
fix pkgs
{ a = 100; b = 300; }
概念的には、pkgs (pkgs (..))のように無限に呼び出している
が、Nix言語は遅延評価なので停止する
ここで、以下のようなSetsで、上記のpkgsをoverrideすることを考える
code:nix repl
overrides = { a = 1; }
code:nix repl
fix pkgs // overrides
{ a = 1; b = 300; }
aが上書きされるが、aに依存しているbは何も更新されていない
fix pkgsして値を求めたあとにmergeしているので当然であるmrsekut.icon
ここで、どうにかしてbも上書きした{ a = 1; b = 201; }という値が欲しい
1段階目
code:nix repl
let newpkgs = pkgs overrides; in newpkgs
{ a = 100; b = 201; }
簡約すると
(self: { a = 100; b = self.a + 200; }) { a = 1; }
{a = 100; b = 1 + 200;}
引数のselfは、{ a = 1; }なので、bは上書きされる
aは固定なのでそのまま
2段階目
code:nix repl
let newpkgs = pkgs (overrides); in newpkgs // overrides
{ a = 1; b = 201; }
上の結果に対して、// overridesでmergeしただけ
簡約すると
(self: { a = 100; b = self.a + 200; }) { a = 1; } // { a = 1; }
{a = 100; b = 1 + 200;} // { a = 1; }
{a = 1; b = 201; }
ここでpkgsの引数をnewpkgs // overrridesにしている理由が不明 結果は上と同じになるので、何のためにやっているのかわからんmrsekut.icon
code:nix repl
let newpkgs = pkgs (newpkgs // overrides); in newpkgs
{ a = 100; b = 201; }
code:nix repl
let newpkgs = pkgs (newpkgs // overrides); in newpkgs // overrides
{ a = 1; b = 201; }
参考